package com.jiawa.train.business.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ByteUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jiawa.train.business.domain.DailyTrain;
import com.jiawa.train.business.domain.DailyTrainTicket;
import com.jiawa.train.business.domain.DailyTrainTicketExample;
import com.jiawa.train.business.domain.TrainStation;
import com.jiawa.train.business.enums.SeatTypeEnum;
import com.jiawa.train.business.enums.TrainTypeEnum;
import com.jiawa.train.business.mapper.DailyTrainTicketMapper;
import com.jiawa.train.business.req.DailyTrainTicketQueryReq;
import com.jiawa.train.business.req.DailyTrainTicketSaveReq;
import com.jiawa.train.common.resp.PageResult;
import com.jiawa.train.common.util.SnowUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class DailyTrainTicketService {
    //reource是使用名称注入的方式而autowired是使用类型注入的方式
    @Resource
    private DailyTrainTicketMapper dailyTrainTicketMapper;

    @Resource
    private TrainStationService trainStationService;

    @Resource
    private DailyTrainSeatService dailyTrainSeatService;
    //新增或者更新用户信息，通过判断是否有id决定进行新增操作还是更新操作
    public void save(DailyTrainTicketSaveReq req) {
        //将传递的参数赋给DailyTrainTicket对象,在req中没有id,createTime,updateTime的数据，需要自己进行赋值
        //这里的id使用雪花算法，然后创建时间使用当前时间
        DateTime now = DateTime.now();
        DailyTrainTicket dailyTrainTicket = BeanUtil.copyProperties(req, DailyTrainTicket.class);
        //如果id为空，则进行新增操作
        if(ObjectUtil.isNull(dailyTrainTicket.getId())){
            dailyTrainTicket.setId(SnowUtil.getSnowflakeNextId());
            dailyTrainTicket.setCreateTime(now);
            dailyTrainTicket.setUpdateTime(now);
            dailyTrainTicketMapper.insert(dailyTrainTicket);
        }
        //否则进行更新操作
        else{
            dailyTrainTicket.setUpdateTime(now);
            dailyTrainTicketMapper.updateByPrimaryKeySelective( dailyTrainTicket);
        }
    }

//    询数据库，将数据存入缓存中
//    @CachePut(value = "DailyTrainTicket", key = "#req.trainCode + '-' + #req.start + '-' + #req.end + '-' + #req.date + '-' + #req.page + '-' + #req.pageSize")
//    public PageResult queryDailyTrainTicketList2(DailyTrainTicketQueryReq req) {
//        return queryDataBase(req);
//    }
//
    //查询缓存数据
    @Cacheable(value = "DailyTrainTicket", key = "#req.trainCode + '-' +  #req.start + '-' + #req.end + '-' + #req.date + '-' + #req.page + '-' + #req.pageSize")
    public PageResult queryDailyTrainTicketList(DailyTrainTicketQueryReq  req) {
      return queryDataBase(req);
    }
    //如果用户id存在则进行根据id进行查询乘客的信息，如果是用户id不存在则进行查询所有,全部都按分页进行处理
    public PageResult queryDataBase(DailyTrainTicketQueryReq  req) {
        //创建dailyTrainTicketExample对象
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        dailyTrainTicketExample.setOrderByClause("date desc,train_code asc,start_index asc");
        DailyTrainTicketExample.Criteria criteria = dailyTrainTicketExample.createCriteria();
        if(ObjectUtil.isNotNull(req.getTrainCode())){
            criteria.andTrainCodeEqualTo(req.getTrainCode());
        }
        if(ObjectUtil.isNotNull(req.getDate())){
            criteria.andDateEqualTo(req.getDate());
        }
        if(ObjectUtil.isNotNull(req.getStart())){
            criteria.andStartEqualTo(req.getStart());
        }
        if(ObjectUtil.isNotNull(req.getEnd())){
            criteria.andEndEqualTo(req.getEnd());
        }
        log.info("查询参数：{}", req);
        // 先设置分页的参数
        PageHelper.startPage(req.getPage(),req.getPageSize());
        //进行查询数据库
        List<DailyTrainTicket> dailyTrainTicketList = dailyTrainTicketMapper.selectByExample(dailyTrainTicketExample);
        //返回查询结果,转为分页的形式,
        PageInfo<DailyTrainTicket> pageInfo = new PageInfo<>(dailyTrainTicketList);
        //获取数据进行封装
        PageResult pageResult = new PageResult(pageInfo.getTotal(), pageInfo.getList());
        //返回查询结果
        return pageResult;
    }
    public void delete(Long id) {
        dailyTrainTicketMapper.deleteByPrimaryKey(id);
    }

    //根据每日车次，日期，车次信息生成每日余票信息
    @Transactional
    public void genDailyTicket(DailyTrain dailyTrain, Date date, String trainCode) {
        DateTime now = DateTime.now();
        //1.首先删除该日期下的该车次的座位信息
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        DailyTrainTicketExample.Criteria criteria = dailyTrainTicketExample.createCriteria();
        criteria.andDateEqualTo(date);
        criteria.andTrainCodeEqualTo(trainCode);
        dailyTrainTicketMapper.deleteByExample(dailyTrainTicketExample);
       //2.查询该车次的车站的信息
        List<TrainStation> trainStationList = trainStationService.selectByTrainCode(trainCode);
        if(CollUtil.isEmpty(trainStationList)){
            log.info("没有查询到该车次车站信息");
            return;
        }
        //3.遍历车站的信息，然后生成每日的余票信息
        //出发站
        for (int i = 0; i < trainStationList.size() - 1; i++) {
            TrainStation trainStationStart = trainStationList.get(i);
            BigDecimal sumKm = BigDecimal.ZERO;
            //终点站
            for(int j = i + 1; j < trainStationList.size(); j++){
                TrainStation trainStationEnd = trainStationList.get(j);
                //计算到不同站点的里程数
                sumKm = sumKm.add(trainStationEnd.getKm());
                DailyTrainTicket dailyTrainTicket = new DailyTrainTicket();
                dailyTrainTicket.setId(SnowUtil.getSnowflakeNextId());
                dailyTrainTicket.setDate(date);
                dailyTrainTicket.setTrainCode(trainCode);
                dailyTrainTicket.setStart(trainStationStart.getName());
                dailyTrainTicket.setStartPinyin(trainStationStart.getNamePinyin());
                dailyTrainTicket.setStartTime(trainStationStart.getOutTime());
                //使用byte类型存储索引
                dailyTrainTicket.setStartIndex(ByteUtil.intToByte(trainStationStart.getIndex()));
                dailyTrainTicket.setEnd(trainStationEnd.getName());
                dailyTrainTicket.setEndPinyin(trainStationEnd.getNamePinyin());
                dailyTrainTicket.setEndTime(trainStationEnd.getInTime());
                dailyTrainTicket.setEndIndex(ByteUtil.intToByte(trainStationEnd.getIndex()));
                int ydz = dailyTrainSeatService.countSeat(date, trainCode, SeatTypeEnum.YDZ.getCode());
                int edz = dailyTrainSeatService.countSeat(date, trainCode, SeatTypeEnum.EDZ.getCode());
                int rw = dailyTrainSeatService.countSeat(date, trainCode, SeatTypeEnum.RW.getCode());
                int yw = dailyTrainSeatService.countSeat(date, trainCode, SeatTypeEnum.YW.getCode());
                // 票价 = 里程之和 * 座位单价 * 车次类型系数
                String trainType = dailyTrain.getType();
                // 计算票价系数：TrainTypeEnum.priceRate
                BigDecimal priceRate = EnumUtil.getFieldBy(TrainTypeEnum::getPriceRate, TrainTypeEnum::getCode, trainType);
                BigDecimal ydzPrice = sumKm.multiply(SeatTypeEnum.YDZ.getPrice()).multiply(priceRate).setScale(2, RoundingMode.HALF_UP);
                BigDecimal edzPrice = sumKm.multiply(SeatTypeEnum.EDZ.getPrice()).multiply(priceRate).setScale(2, RoundingMode.HALF_UP);
                BigDecimal rwPrice = sumKm.multiply(SeatTypeEnum.RW.getPrice()).multiply(priceRate).setScale(2, RoundingMode.HALF_UP);
                BigDecimal ywPrice = sumKm.multiply(SeatTypeEnum.YW.getPrice()).multiply(priceRate).setScale(2, RoundingMode.HALF_UP);
                dailyTrainTicket.setYdz(ydz);
                dailyTrainTicket.setYdzPrice(ydzPrice);
                dailyTrainTicket.setEdz(edz);
                dailyTrainTicket.setEdzPrice(edzPrice);
                dailyTrainTicket.setRw(rw);
                dailyTrainTicket.setRwPrice(rwPrice);
                dailyTrainTicket.setYw(yw);
                dailyTrainTicket.setYwPrice(ywPrice);
                dailyTrainTicket.setCreateTime(now);
                dailyTrainTicket.setUpdateTime(now);
                dailyTrainTicketMapper.insert(dailyTrainTicket);

            }
        }
    }

    //使用每日车票唯一键(id)的方式获取余票的相关信息
    public DailyTrainTicket getDailyTrainTicket(Date date, String trainCode, String start, String end) {
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        DailyTrainTicketExample.Criteria criteria = dailyTrainTicketExample.createCriteria();
        criteria.andDateEqualTo(date);
        criteria.andTrainCodeEqualTo(trainCode);
        criteria.andStartEqualTo(start);
        criteria.andEndEqualTo(end);
        //使用该种方法获取的是一个列表
        List dailyTrainTicketList = dailyTrainTicketMapper.selectByExample(dailyTrainTicketExample);
        if(CollUtil.isEmpty(dailyTrainTicketList)){
            return null;
        }
        else{
            return (DailyTrainTicket) dailyTrainTicketList.get(0);
        }
    }
}